package com.ttt.game;

import com.ttt.map.GameMap;
import com.ttt.tank.EnemyTank;
import com.ttt.tank.HisTank;
import com.ttt.tank.MyTank;
import com.ttt.tank.Tank;
import com.ttt.util.MusicUtil;
import com.ttt.util.MyUtil;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import static com.ttt.util.Constant.*;
public class GameFrame extends Frame implements Runnable{
    //第一次使用的时候加载，而不是类加载的时候加载
    private Image overImg = null;
    private Image helpImg;
    private Image aboutImg;

    //定义一张和屏幕大小一致的图片(双缓存技术解决画面闪烁问题)
    private BufferedImage bufImg = new BufferedImage(Frame_Width,Frame_Height,BufferedImage.TYPE_4BYTE_ABGR);

    private static int gameState;
    private static int menuIndex;
    //标题栏高度
    public static int titleBraH;

    private static Tank myTank;

    private static Tank hisTank;
    //敌人的坦克容器
    private static List<Tank> enemies = new ArrayList<>();

    //用来记录本关卡产生了多少个敌人
    private static int bornEnemyCount;

    //用来记录消灭敌人的数量
    public static int killEnemyCount;

    //定义地图相关的内容
    private static GameMap  gameMap = new GameMap();

    public GameFrame(){
        initFrame();

        initEventListener();
        //启动用于刷新窗口的线程
        new  Thread(this).start();
    }

    /**
     * 对游戏进行初始化
     */
    private void initGame(){
        gameState = State_Menu;
    }
    private void initFrame(){
        setTitle(Game_Title);
        setSize(Frame_Width,Frame_Height);
        setLocation(Frame_x,Frame_y);
        setVisible(true);
        setResizable(false);
        //求标题栏的高度
        titleBraH = getInsets().top;

    }

    /**
     *
     * @param g1 系统提供的画笔，系统进行初始化
     */

    public void update(Graphics g1){
        //得到图片的画笔
        Graphics g = bufImg.getGraphics();
        g.setFont(gameFont);
        switch (gameState){
            case State_Menu:
                drawMenu(g);
                break;
            case State_Help:
                drawHelp(g);
                break;
            case State_About:
                drawAbout(g);
                break;
            case State_Run:
                drawRun(g);
                break;
            case State_Lost:
                drawLost(g,"游戏失败");
                break;
            case State_Win:
                drawWin(g);
                break;
            case State_Cross:
                drawCross(g);
                break;
        }

        //使用系统画笔,将图片绘制到frame上来
        g1.drawImage(bufImg,0,0,null);
    }

    /**
     * 绘制游戏结束的方法
     * @param g 参数
     */
    private void drawLost(Graphics g,String str) {
        //保证只加载一次
        if (overImg == null){
            overImg = MyUtil.createImage("images/over.jpg");
        }
        //黑背景填充，可以使得看不见原有内容
        g.setColor(Color.black);
        g.fillRect(0,0,Frame_Width,Frame_Height);

        int imgW = overImg.getWidth(null);
        int imgH = overImg.getHeight(null);
        g.drawImage(overImg,Frame_Width - imgW >> 1,Frame_Height - imgH >> 1,null);
        //添加按键的提示信息
        g.setColor(Color.white);
        g.drawString(Over_Str0,10,Frame_Height - 40);
        g.drawString(Over_Str1,Frame_Width - 280,Frame_Height - 40);
        //失败文字
        g.setColor(Color.white);
        g.drawString(str,Frame_Width/2 - 30,100);
    }

    /**
     * 绘制游戏胜利的界面
     * @param g 参数
     */
    private void drawWin(Graphics g){
        drawLost(g,"游戏通关");
    }

    private void drawRun(Graphics g) {
        g.setColor(new Color(19, 35, 10));
        g.fillRect(0,0,Frame_Width,Frame_Height);

        //绘制地图的碰撞层
        gameMap.drawBk(g);

        drawEnemies(g);

        myTank.draw(g);

        hisTank.draw(g);

        //绘制地图的遮挡层
        gameMap.drawCover(g);

        drawExplodes(g);
        //子弹和坦克的碰撞的方法
        bulletCollideTank();
        //System.out.println(myTank);

        //子弹和所有的地图块的碰撞
        bulletAndTankCollideMapWall();
    }
    //绘制所有敌人坦克,如果敌人已经死亡，从容器中移除
    private void drawEnemies(Graphics g){
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            if (enemy.isDie()){
                enemies.remove(i);
                i--;
                continue;
            }
            enemy.draw(g);
        }
//        System.out.println("敌人数量:"+enemies.size());
    }

    /**
     * 绘制游戏帮助界面的内容
     * @param g 参数
     */
    private void drawAbout(Graphics g) {
        //TODO
        g.setColor(Color.black);
        g.fillRect(0,0,Frame_Width,Frame_Height);
        if (aboutImg == null){
            aboutImg = MyUtil.createImage("images/");
        }
        int width = aboutImg.getWidth(null);
        int height = aboutImg.getHeight(null);

        int x = Frame_Width - width >> 1;
        int y = Frame_Height - height >> 1;
        g.drawImage(aboutImg,x,y,null);
        g.setColor(Color.white);
        g.drawString("任意键继续",20,Frame_Height - 20);
    }

    private void drawHelp(Graphics g) {
        //TODO
        g.setColor(Color.black);
        g.fillRect(0,0,Frame_Width,Frame_Height);
        if (helpImg == null){
            helpImg = MyUtil.createImage("images/");
        }
        int width = helpImg.getWidth(null);
        int height = helpImg.getHeight(null);

        int x = Frame_Width - width >> 1;
        int y = Frame_Height - height >> 1;
        g.drawImage(helpImg,x,y,null);
        g.setColor(Color.white);
        g.drawString("任意键继续",20,Frame_Height - 20);
    }

    private void drawMenu(Graphics g){
        g.setColor(new Color(124, 138, 35));
        g.fillRect(0,0,Frame_Width,Frame_Height);
        final int Str_Width = 80;
        int x = Frame_Width - Str_Width >> 1;
        int y = Frame_Height / 3;
        final int DIS = 60;
        g.setColor(Color.white);
        for (int i = 0;i < Menus.length;i++){
            if (i == menuIndex){
                g.setColor(Color.RED);
            }else {
                g.setColor(Color.white);
            }
            g.drawString(Menus[i],x,y+DIS*i);
        }
    }

    private void initEventListener(){
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        addKeyListener(new KeyAdapter() {
            //按键按下回调方法
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (gameState){
                    case State_Menu:
                        keyPressedEventMenu(keyCode);
                        break;
                    case State_Help:
                        keyPressedEventHelp(keyCode);
                        break;
                    case State_About:
                        keyPressedEventAbout(keyCode);
                        break;
                    case State_Run:
                        keyPressedEventRun(keyCode);
                        break;
                    case State_Lost:
                        keyPressedEventLost(keyCode);
                        break;
                    case State_Win:
                        keyPressedEventWin(keyCode);
                        break;
                }
            }
            //按键松开回调方法
            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (gameState){
                    case State_Menu:
                        keyReleasedEventMenu(keyCode);
                        break;
                    case State_Help:
                        keyReleasedEventHelp(keyCode);
                        break;
                    case State_About:
                        keyReleasedEventAbout(keyCode);
                        break;
                    case State_Run:
                        keyReleasedEventRun(keyCode);
                        break;
                    case State_Lost:
                        keyReleasedEventOver(keyCode);
                        break;
                }

            }
        });
    }

    private void keyReleasedEventOver(int keyCode) {
    }

    private void keyReleasedEventAbout(int keyCode) {
    }

    private void keyReleasedEventHelp(int keyCode) {
    }

    private void keyReleasedEventMenu(int keyCode) {
    }

    private void keyReleasedEventRun(int keyCode) {
        switch (keyCode){
            case KeyEvent.VK_W:
            case KeyEvent.VK_S:
            case KeyEvent.VK_A:
            case KeyEvent.VK_D:
                myTank.setState(Tank.State_Stand);
                break;
            case KeyEvent.VK_UP:
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_RIGHT:
                hisTank.setState(Tank.State_Stand);
                break;

        }
    }

    //游戏结束的按键处理
    private void keyPressedEventLost(int keyCode) {
        //结束游戏
        if (keyCode == KeyEvent.VK_ESCAPE){
            System.exit(0);
        }else if (keyCode == KeyEvent.VK_ENTER){
            setGameState(State_Menu);
            //游戏的操作关闭，游戏的一些属性需要重置
            resetGame();
        }
    }
    //游戏通关的按键处理
    private void keyPressedEventWin(int keyCode) {
        keyPressedEventLost(keyCode);
    }

    //重置游戏状态
    private void resetGame(){
        killEnemyCount = 0;
        menuIndex = 0;
        //友方坦克子弹还回对象池
        myTank.bulletsReturn();
        //销毁自己的坦克
        myTank = null;
        for (Tank enemy : enemies) {
            enemy.bulletsReturn();
        }
        //清空敌人坦克
        enemies.clear();
        //清空地图资源
        gameMap = null;
    }

    //游戏运行中的按键处理
    private void keyPressedEventRun(int keyCode) {
        MusicUtil.playStart();
        switch (keyCode){
            case KeyEvent.VK_W:
                myTank.setDir(Tank.Dir_Up);
                myTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_UP:
                hisTank.setDir(Tank.Dir_Up);
                hisTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_S:
                myTank.setDir(Tank.Dir_Down);
                myTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_DOWN:
                hisTank.setDir(Tank.Dir_Down);
                hisTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_A:
                myTank.setDir(Tank.Dir_Left);
                myTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_LEFT:
                hisTank.setDir(Tank.Dir_Left);
                hisTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_D:
                myTank.setDir(Tank.Dir_Right);
                myTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_RIGHT:
                hisTank.setDir(Tank.Dir_Right);
                hisTank.setState(Tank.State_Move);
                break;
            case KeyEvent.VK_G:
                myTank.fire();
                break;
            case KeyEvent.VK_K:
                hisTank.fire();
                break;
        }

    }

    private void keyPressedEventAbout(int keyCode) {
        setGameState(State_Menu);
    }

    private void keyPressedEventHelp(int keyCode) {
        setGameState(State_Menu);
    }

    //菜单状态下的按键处理
    private void keyPressedEventMenu(int keyCode) {
        switch (keyCode){
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                if (--menuIndex < 0){
                    menuIndex = Menus.length - 1;
                }
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                if (++menuIndex > Menus.length - 1){
                    menuIndex = 0;
                }
                break;
            case KeyEvent.VK_ENTER:
                switch (menuIndex){
                    //TODO
                    case 0:
                        startGame(1);
                        break;
                    case 1:
                        //继续游戏 进入选择关卡的界面
                        break;
                    case 2:
                        setGameState(State_Help);
                        break;
                    case 3:
                        setGameState(State_About);
                        break;
                    case 4:
                        System.exit(0);
                        break;
                }
                break;
        }
    }

    /**
     * 开始游戏的方法
     * 并加载level关卡信息
     * @param level
     */
    private static void startGame(int level) {
        enemies.clear();
        if (gameMap == null){
            gameMap = new GameMap();
        }
        gameMap.initMap(level);
        //导入音频
        MusicUtil.playBgm();
        killEnemyCount = 0;
        bornEnemyCount = 0;
        gameState = State_Run;
        myTank = new MyTank(Frame_Width/3,Frame_Height-Tank.Radius*2,Tank.Dir_Up);
        hisTank = new HisTank(Frame_Width - Frame_Width/3,Frame_Height-Tank.Radius*2,Tank.Dir_Up);
        //使用一个单独的线程用于控制生产敌人的坦克
        new Thread(){
            @Override
            public void run(){
                while (true){
                    if (LevelInof.getInstance().getEnemyCount() > bornEnemyCount
                    && enemies.size() < Enemy_Max_Count){
                        Tank enemy = EnemyTank.createEnemy();
                        enemies.add(enemy);
                        bornEnemyCount++;
                    }
                    try{
                        Thread.sleep(Enemy_Born_Interval);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    //只有在游戏run状态才创建敌人坦克
                    if (gameState != State_Run){
                        break;
                    }
                }
            }
        }.start();
    }

    @Override
    public void run() {
        while (true){
            repaint();
            try {
                Thread.sleep(Repaint_Interval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //敌人的坦克的子弹和我的坦克的碰撞
    //我的坦克的子弹和所有的敌人的碰撞
    //敌人的坦克的子弹和他的坦克的碰撞
    //他的坦克的子弹和所有的敌人的碰撞
    private void bulletCollideTank(){
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            enemy.collideBullets(myTank.getBullets());
            enemy.collideBullets(hisTank.getBullets());
        }
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            myTank.collideBullets(enemy.getBullets());
            hisTank.collideBullets(enemy.getBullets());
            myTank.collideBullets(hisTank.getBullets());
        }
//        for (Tank enemy : enemies){
//            enemy.collideBullets(myTank.getBullets());
//        }
//
//        for (Tank enemy : enemies){
//            myTank.collideBullets(enemy.getBullets());
//        }
    }
    private void drawExplodes(Graphics g){
//        for (Tank enemy : enemies) {
//            enemy.drawExplodes(g);
//        }
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            enemy.drawExplodes(g);
        }
        myTank.drawExplodes(g);
    }

    //所有的子弹和地图块的碰撞
    private void bulletAndTankCollideMapWall(){
        //自己坦克的子弹和地图块的碰撞
       myTank.bulletsCollideMapWalls(gameMap.getWalls());
       hisTank.bulletsCollideMapWalls(gameMap.getWalls());
       //敌人的坦克的子弹和地图块的碰撞
//        for (Tank enemy : enemies) {
//            enemy.bulletsCollideMapWalls(gameMap.getWalls());
//        }
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            enemy.bulletsCollideMapWalls(gameMap.getWalls());
        }
        //坦克和地图的碰撞
        if (myTank.isCollideWall(gameMap.getWalls())){
            myTank.back();
        }
        if (hisTank.isCollideWall(gameMap.getWalls())){
            hisTank.back();
        }
        //敌人的坦克和地图的碰撞
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            if (enemy.isCollideWall(gameMap.getWalls())){
                enemy.back();
            }
        }
        //清理所有的被销毁的地图块
        gameMap.clearDestoryWall();
    }

    /**
     * 是否是最后一关
     * @return
     */
    public static boolean isLastLevel(){
        //当前关卡和总关卡一致
        int currLevel = LevelInof.getInstance().getLevel();
        int levelCount = GameInfo.getLevelCount();
        return currLevel == levelCount;
    }

    /**
     * 判断是否过关了
     * @return
     */
    public static boolean isCrossLevel(){
        //消灭敌人的数量和关卡的敌人的数量一致
        return  killEnemyCount == LevelInof.getInstance().getEnemyCount();
    }

    /**
     * 进入下一关的方法
     */
    public static void nextLevel() {
        startGame(LevelInof.getInstance().getLevel() + 1);
    }
    //开始过关动画
    public static int flashTime;
    public static final int Rect_Width = 40;
    public static final int Rect_Count = Frame_Width/Rect_Width + 1;
    public static boolean isOpen = false;
    public static void  startCrossLevel(){
        gameState = State_Cross;
        flashTime = 0;
        isOpen = false;
//        GameFrame.nextLevel();
    }
    //绘制过关动画
    public void drawCross(Graphics g){
        gameMap.drawBk(g);
        myTank.draw(g);
        hisTank.draw(g);
        gameMap.drawCover(g);

        g.setColor(Color.black);
        //关闭百叶窗的效果
        if (isOpen){
            for (int i = 0; i < Rect_Count; i++) {
                g.fillRect(i * Rect_Width,0,flashTime,Frame_Height);
            }
            //所有的叶片都关闭了
            if (flashTime++ - Rect_Width > 5){
                isOpen = true;
                //初始化下一关地图
                gameMap.initMap(LevelInof.getInstance().getLevel() + 1);
            }
        }else {
            for (int i = 0; i < Rect_Count; i++) {
                g.fillRect(i * Rect_Width,0,flashTime,Frame_Height);
            }
            if (flashTime-- == 0){
                startGame(LevelInof.getInstance().getLevel() + 1);
            }
        }
    }

    public static void setGameState(int gameState) {
        GameFrame.gameState = gameState;
    }

    //获得游戏状态和修改游戏状态
    public static int getGameState() {
        return gameState;
    }
}
